/*
 * @Description:
 * @Version: 2.0
 * @Autor: 许国辉
 * @Date: 2022-10-26 07:57:15
 * @LastEditors: 许国辉
 * @LastEditTime: 2024-09-20 14:46:24
 */
import * as xlsx from 'xlsx';
import type { WorkBook } from 'xlsx';
import type { JsonToSheet, AoAToSheet } from './typing';
import FileSaver from 'file-saver';
import XLSXStyle from 'xlsx-style-vite';

const { utils, writeFile } = xlsx;

const DEF_FILE_NAME = 'excel-list.xlsx';

export function jsonToSheetXlsx<T = any>({
  data,
  header,
  filename = DEF_FILE_NAME,
  json2sheetOpts = { row: true },
}: // write2excelOpts = { bookType: 'xlsx' },
JsonToSheet<T>) {
  const cols = [{}];
  const arrData = [...data];
  if (header) {
    arrData.unshift(header);
    json2sheetOpts.skipHeader = true;
    Object.keys(header).forEach(() => {
      cols.push({ wch: 15 });
    });
  }

  const worksheet = utils.json_to_sheet(arrData, json2sheetOpts);

  // console.log(header);

  cols[0] = { wch: 8 };
  /* add worksheet to workbook */
  const workbook: WorkBook = {
    SheetNames: [filename],
    Sheets: {
      [filename]: worksheet,
    },
  };

  worksheet['!cols'] = cols;
  /* output format determined by filename */
  setExlStyle(workbook['Sheets'][filename]); // 设置列宽 字号等
  //addRangeBorder(workbook['Sheets'][filename]['!merges'], workbook['Sheets'][filename]);
  const wbout = XLSXStyle.write(workbook, { bookType: 'xlsx', bookSST: false, type: 'binary' });
  FileSaver.saveAs(
    new Blob([s2ab(wbout)], {
      type: 'application/octet-stream',
    }),
    filename,
  );
  // writeFile(workbook, filename, write2excelOpts);
  /* at this point, out.xlsb will have been downloaded */
}

export function aoaToSheetXlsx<T = any>({
  data,
  header,
  filename = DEF_FILE_NAME,
  write2excelOpts = { bookType: 'xlsx' },
}: AoAToSheet<T>) {
  const arrData = [...data];
  if (header) {
    arrData.unshift(header);
  }

  const worksheet = utils.aoa_to_sheet(arrData);

  /* add worksheet to workbook */
  const workbook: WorkBook = {
    SheetNames: [filename],
    Sheets: {
      [filename]: worksheet,
    },
  };

  setExlStyle(workbook['Sheets'][filename]); // 设置列宽 字号等
  //addRangeBorder(workbook['Sheets'][filename]['!merges'], workbook['Sheets'][filename]);
  /* output format determined by filename */
  writeFile(workbook, filename, write2excelOpts);
  /* at this point, out.xlsb will have been downloaded */
}

function s2ab(s) {
  const buf = new ArrayBuffer(s.length);
  const view = new Uint8Array(buf);
  for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
  return buf;
}

const setExlStyle = (data) => {
  const borderAll = {
    //单元格外侧框线
    top: {
      style: 'thin',
    },
    bottom: {
      style: 'thin',
    },
    left: {
      style: 'thin',
    },
    right: {
      style: 'thin',
    },
  };
  //data['!cols'] = [];
  for (const key in data) {
    if (data[key] instanceof Object) {
      data[key].s = {
        border: borderAll,
        alignment: {
          horizontal: 'center', //水平居中对齐
          vertical: 'center',
        },
        font: {
          sz: 11,
        },
        bold: true,
        numFmt: 0,
      };
      //data['!cols'].push({ wpx: 115 });
    }
  }
  return data;
};

// const addRangeBorder = (range, ws) => {
//   const cols = [
//     'A',
//     'B',
//     'C',
//     'D',
//     'E',
//     'F',
//     'G',
//     'H',
//     'I',
//     'J',
//     'K',
//     'L',
//     'M',
//     'N',
//     'O',
//     'P',
//     'Q',
//     'R',
//     'S',
//     'T',
//     'U',
//     'V',
//     'W',
//     'X',
//     'Y',
//     'Z',
//   ];
//   if (range) {
//     range.forEach((item) => {
//       const style = {
//         s: {
//           border: {
//             top: { style: 'thin' },
//             left: { style: 'thin' },
//             bottom: { style: 'thin' },
//             right: { style: 'thin' },
//           },
//         },
//       };
//       // 处理合并行
//       for (let i = item.s.c; i <= item.e.c; i++) {
//         ws[`${cols[i]}${Number(item.e.r) + 1}`] = ws[`${cols[i]}${Number(item.e.r) + 1}`] || style;
//         // 处理合并列
//         for (let k = item.s.r + 2; k <= item.e.r + 1; k++) {
//           ws[cols[i] + k] = ws[cols[k] + item.e.r] || style;
//         }
//       }
//     });
//   }

//   return ws;
// };
